import inspect
import os
import glob
import sys
import openpyxl
from openpyxl import load_workbook
import copy

def StrStrip(str_in):
    return str_in if str_in is None else str(str_in).strip()


"""
数据结构:
    sheet_dic[sheetname] = {
        'sheetname': sheet , # 存储sheet名称
        'wb': wb,    # 存储工作簿对象
        'file': file # 存储文件名称
    }
    
    peripherals_overview_infos[peripheral_name][_partname] = {
        'sheetname': sheetname ,
        'wb': sheet_dic[sheetname]['wb'] ,
        'file': sheet_dic[sheetname]['file']  
    }
"""

# sheet name of device\cpu\peripheral overview
device_info_sheets = ["DEVICE","CPU","PERIPHERALS"]

# part ot sheet name of peripheral detail and map
part_name_of_peripheral_info_sheet = ["MAP","DETAIL"]

field_reserve_list = ["reserve","reserved",'r_'] # all in lower case

field_enum_parameter_list = ["headerEnumName","enumValueName","enumValue",'enumDescription']


valid_header_MAP = ['addressOffset', 'name', 'resetValue', 'description','dim','dimIncrement','dimIndex']
valid_header_DETAIL = ['regname','name','msb','lsb','access','description',"headerEnumName","enumValueName","enumValue",'enumDescription','dim','dimIncrement','dimIndex','modifiedWriteValues','writeConstraint','readAction']
valid_header_DEVICE = ['name', 'description', 'version', 'addressUnitBits', 'width', 'size', 'resetValue', 'resetMask']
valid_header_CPU = ['name', 'revision', 'endian', 'mpuPresent', 'fpuPresent', 'nvicPrioBits', 'vendorSystickConfig']
valid_header_PERIPHERAL = ['name', 'BUS', 'groupName', 'sheetName', 'headerStructName', 'baseAddress', 'offset', 'size', 'description', 'interrupt', 'int_name', 'int_description']

peripheral_paras = ['name', 'BUS', 'groupName', 'sheetName', 'headerStructName', 'baseAddress', 'offset', 'size', 'description']

def read_sheetinfos(files_paths) -> dict:
    """
    从输入的xlsx文件中读取所有sheet的信息
    
    参数:
    - files_paths: 文件路径列表
    
    返回:
    - 一个字典,包含所有sheet的信息,key是sheet名称,value是sheet的信息
    """    
    
    sheet_dic = {} 
    
    for file in files_paths:
        try:
            wb = load_workbook(file, data_only=True)  # data_only=True意味着读取公式计算后的值
            sheet_names = wb.sheetnames  
            
            # 将每个工作表名称作为键，存储文件名和Excel对象
            for sheet in sheet_names:
                sheet_dic[sheet] = {
                    'sheetname': sheet ,
                    'wb': wb,  # 存储工作簿对象
                    'file': file
                }
        except Exception as e:
            print(f"读取文件时发生错误,可能被打开: {e}")
            continue
    
    if len(sheet_dic) == 0:
        print("没有找到任何sheet")
        return None
    
    return sheet_dic

def read_key_and_value_pairs(one_in_sheet_dic :dict,valid_header=[]) -> dict:
    """
    从固定格式的工作表中获取键值对。
    固定格式：表头(第一行)是属性名称，第二行是对应属性的值,且只有这两行
    
    参数:
    - one_in_sheet_dic: 已经获取到的工作簿和工作表数据的字典。
    
    返回:
    - 一个字典，属性和值的键值对
    """
    
    
    try:
        sheetname = one_in_sheet_dic['sheetname']
        wb = one_in_sheet_dic['wb']  
        sheet = wb[sheetname]  
        file_path = one_in_sheet_dic['file']  
    except Exception as e:
        print(f"[Error]读取Sheet\"{sheetname}\"时发生错误: {e}")
        return None

    result = {}
    
    # 获取表头
    header_row=1
    value_row=2
    header = [cell.value for cell in sheet[header_row]]
        
    # 检查实际表头是否与预期一致
    if valid_header is not None and len(valid_header) > 0:
        h0 = valid_header
        h1 = header
        if set(h1) != set(h0):
            missing = set(h0) - set(h1)
            extra = set(h1) - set(h0)
            print(f"[Forbidden] 表头检查不一致: 缺少 {missing}, 额外有 {extra} 在文件 {file_path}")
            sys.exit(11)
    
    # 获取每列的第一个值
    for col in header:
        col_index = header.index(col) + 1  # openpyxl的列索引从1开始
        result[col] = sheet.cell(row=value_row, column=col_index).value  # 获取指定行的值

    # print(f"{inspect.currentframe().f_code.co_name}:{sheetname}:", result)
    
    return result


def read_multi_key_and_valuedict_pairs(one_in_sheet_dic :dict, index_form_0_of_col_as_key: int = 0,valid_header=[]) -> dict:
    """
    从固定格式的工作表中获取键值对的字典,字典的key以index_form_0_of_col_as_key指定
    固定格式：表头(第一行)是属性名称，从第二行往下都是是对应属性的值
    
    参数:
    - one_in_sheet_dic: 已经获取到的工作簿和工作表数据的字典。
    - index_form_0_of_col_as_key: 指定列为输出字典的Key,默认为0,就是第一列
    
    返回:
    - 一个多同类对象的属性和值的键值对的字典,字典的key是对象名称,value是对象的属性的字典
    {
        "Key1" : dic1
        "Key2" : dic2
    }
    """
    
    try:
        sheetname = one_in_sheet_dic['sheetname']
        wb = one_in_sheet_dic['wb']  
        sheet = wb[sheetname]  
        file_path = one_in_sheet_dic['file']  
    except Exception as e:
        print(f"读取Sheet\"{sheetname}\"时发生错误: {e}")
        return None  
    
    result = {}
    
    # 读取表头
    header = [cell.value for cell in sheet[1]]  #rowindex 从1开始，col index从0开始，总觉得怎么这么狗血
        
    # 检查实际表头是否与预期一致
    if valid_header is not None and len(valid_header) > 0:
        h0 = valid_header
        h1 = header
        if set(h1) != set(h0):
            missing = set(h0) - set(h1)
            extra = set(h1) - set(h0)
            print(f"[Forbidden] 表头检查不一致: 缺少 {missing}, 额外有 {extra} 在文件 {file_path}")
            sys.exit(11)
            
    row_count = sheet.max_row  # 获取总行数
    row_cnt = 0
    for row in sheet.iter_rows(min_row=2, max_row=row_count, values_only=True):  # 从第二行开始读取数据
        key = row[index_form_0_of_col_as_key] 
        row_cnt = row_cnt + 1
        
        # 防止key是None
        if key is None:
            print(f"[Notice] peripheral [Name=None] Skipping sheet:{sheetname} row:{row_cnt}")
            continue  
        
        # 检查 key 是否已经存在于 result 中，已经在了说明信息在表格是重复的，有可能是填错了
        if key in result:
            print(f"[Error] peripheral [{key}] already exists in sheet[{sheetname}] off file[{one_in_sheet_dic['file']}]. Skipping this row.")
            continue  # 跳过这个键
        
        # 将当前行转换为字典，key 为表头，value 为对应的单元格值
        row_dict = {header[i]: row[i] for i in range(len(row))}
        
        # 将字典加入 result
        result[key] = row_dict
    
    #print(f"read_multi_key_and_valuedict_pairs:{sheetname}:", result)
    
    return result


def get_peripheral_overviews(one_in_sheet_dic :dict) -> dict:
    """
    从固定格式的工作表中获取键值对的字典,字典的key以index_form_0_of_col_as_key指定
    固定格式：表头(第一行)是属性名称，从第二行往下都是是对应属性的值
    
    参数:
    - one_in_sheet_dic: 已经获取到的工作簿和工作表数据的字典。
    - index_form_0_of_peripheral_name: 指定列为输出字典的Key,默认为0,就是第一列
    
    返回:
    - 一个多同类对象的属性和值的键值对的字典,字典的key是对象名称,value是对象的属性的字典
    {
        "Key1" : dic1
        "Key2" : dic2
    }
    """
    index_form_0_of_peripheral_name = 0
    valid_header = valid_header_PERIPHERAL
    
    try:
        sheetname = one_in_sheet_dic['sheetname']
        wb = one_in_sheet_dic['wb']  
        sheet = wb[sheetname]  
        file_path = one_in_sheet_dic['file']  
    except Exception as e:
        print(f"读取Sheet\"{sheetname}\"时发生错误: {e}")
        return None  
    
    result = {}
    
    # 读取表头
    header = [cell.value for cell in sheet[1]]  #rowindex 从1开始，col index从0开始，总觉得怎么这么狗血
    headerindex = 0
    interruptIndex = -1  
    for index, value in enumerate(header):
        if value == "interrupt":
            interruptIndex = index
            break  # 找到后立即退出循环
    if interruptIndex == -1:
        raise ValueError("找不到 interrupt 字段")
            
        
    # 检查实际表头是否与预期一致
    if valid_header is not None and len(valid_header) > 0:
        h0 = valid_header
        h1 = header
        if set(h1) != set(h0):
            missing = set(h0) - set(h1)
            extra = set(h1) - set(h0)
            print(f"[Forbidden] 表头检查不一致: 缺少 {missing}, 额外有 {extra} 在文件 {file_path}")
            sys.exit(11)
            
    row_count = sheet.max_row  # 获取总行数
    row_cnt = 0
    lastPeripheral = "notinitial"
    for row in sheet.iter_rows(min_row=2, max_row=row_count, values_only=True):  # 从第二行开始读取数据
        peripheral = row[index_form_0_of_peripheral_name] 
        row_cnt = row_cnt + 1
        
        # 防止key是None
        if peripheral is None and (row[interruptIndex] == None or row[interruptIndex] == ""):
            print(f"[Notice] peripheral [Name=None] Skipping sheet:{sheetname} row:{row_cnt}")
            continue  
        elif peripheral is None :
            peripheral = lastPeripheral
        
        lastPeripheral = peripheral  
        
        if lastPeripheral == "DMA" :
            pass
                
        if peripheral not in result:
            # 将当前行转换为字典，
            peripheral_para_dic = {header[i]: row[i] for i in range(len(peripheral_paras))}
            
            # 将字典加入 result
            result[peripheral] = peripheral_para_dic
            result[peripheral]["interrupt"] = []
            
        # 处理中断
        intnum = row[interruptIndex]
        if intnum != None and intnum != "":
            interrupt = {'interrupt':row[interruptIndex], 'int_name':row[interruptIndex+1], 'int_description':row[interruptIndex+2]}
            result[peripheral]["interrupt"].append(interrupt)        
    
    return result

def get_peripheral_alias(peripherals_overview_infos: dict) -> dict:
    """
    从已经获得的peripheral信息中获取alias
    IC起的名称是别名,SVD里的是正式名称,后面操作会在脚本里面把别名替换成正式名称
    
    参数:
    - peripherals_overview_infos: 已经获取到的外设信息的一览表
    
    返回:
    - 一个字典,key是别名,value是正式名称
    """    
    peripheral_alias = {}

    for entry in peripherals_overview_infos.values():
        sheetname = entry["sheetName"]
        name = entry["name"]
        peripheral_alias[sheetname] = name

    return peripheral_alias
def get_peripheral_headerStructNameGroup(peripherals_overview_infos: dict) -> dict:
    """
    从已经获得的peripheral信息中获取headerStructName
    对于属于同一个headerStructNameGroup的外设,后面的操作会在SVD文件里面详细其中第一个外设中详细描述这个外设,其余外设会用derivedFrom引用这个外设
    
    参数:
    - peripherals_overview_infos: 已经获取到的外设信息的一览表
    
    返回:
    - 一个字典,key是headerStructName,value是对应的外设名称
    """
    
    peripheral_headerStructNameGroup = {}

    for entry in peripherals_overview_infos.values():
        header_struct_name = entry["headerStructName"]
        if header_struct_name is None :
            continue
        name = entry["name"]

        # 填充peripheral_headerStructNameGroup字典
        if header_struct_name not in peripheral_headerStructNameGroup:
            peripheral_headerStructNameGroup[header_struct_name] = []
        peripheral_headerStructNameGroup[header_struct_name].append(name)

    return peripheral_headerStructNameGroup

def get_peripheral_derivedFromStr(peripheralsinfo: dict, peripheral_headerStructNameGroup: dict) -> str:
    """
    判断外设是否需要derivedFrom
    :param peripheralsinfo: 特定外设信息字典，包含外设的各项属性
    :param peripheral_headerStructNameGroup: 外设头结构名称组字典，包含每种头结构名称对应的外设列表
    :return: 如果外设的名称是对应外设列表的第一个元素，则返回空字符串""；否则返回该列表的第一个元素
    """
    
    if not "name" in peripheralsinfo:
        return ""
        
    if not "headerStructName" in peripheralsinfo:
        return ""
        
    # 获取外设的"name"和"headerStructName"的值
    peripheral_name = peripheralsinfo.get("name") 
    header_struct_name = peripheralsinfo.get("headerStructName") 
    
    # 如果外设信息header_struct_name是none,说明不需要其它外设引用,需要描述细节
    if header_struct_name is None :
        return ""
    
    # 在peripheral_headerStructNameGroup中获取对应headerStructName的peripheralList
    peripheral_list = peripheral_headerStructNameGroup[header_struct_name]
    
    # 如果name是peripheralList的第一个,则返回"",说明外设需要描述细节,否则返回peripheralList第一元素,对应外设需要使用derivedFrom引用第一个元素,不需要描述外设细节
    if peripheral_list and peripheral_name == peripheral_list[0]: 
        return "" 
    else:
        return peripheral_list[0] if peripheral_list else "" 

def get_peripher_sheetinfos(sheet_dic) -> dict:
    
    # 检查参数是否为 None
    if sheet_dic is None:
        print(f"[Error]GetKeyAndValueParesFromSheet传入的参数 sheet_dic 是 None,请检查。")
        return None
    
    peripherals_overview_infos = {}    
    
    # 遍历sheet_dic，根据条件分配信息
    for sheetname, sheet_info in sheet_dic.items():
        
        #如果是devcelevel的信息表就跳过,这里只处理peripheral的信息表
        if sheetname in device_info_sheets:
            continue
        
        if '_' in sheetname:
            # 分割工作表名称
            parts = sheetname.split('_')
            if len(parts) > 1 :                
                peripheral_name = parts[0].strip()  # 前半部分作为key
                
                #检查后半部分,如果不在part_name_of_peripheral_info_sheet里面,则说明不认识
                part_sheetinfo_of_peripheral = parts[1].strip()  # 后半部分作为部分信息
                if not part_sheetinfo_of_peripheral in part_name_of_peripheral_info_sheet:
                    print(f"[Error]名字非法格式的sheet:[{sheetname}] from file [{sheet_dic[sheetname]['file']}]")
                    
                # 存储到peripherals_sheet中
                if peripheral_name not in peripherals_overview_infos:
                    peripherals_overview_infos[peripheral_name] = {}  # 初始化为一个空dict
                    
                peripherals_overview_infos[peripheral_name][part_sheetinfo_of_peripheral] = {
                    'sheetname': sheetname ,
                    'wb': sheet_info['wb'] ,
                    'file': sheet_info['file']  
                }
            else : 
                # 非法格式, sheet名字必须为peripheralname_subpage,subpage必须为
                print(f"[Error]名字非法格式的sheet:[{sheetname}] from file [{sheet_dic[sheetname]['file']}]")
    
    return peripherals_overview_infos


def read_reg_map_back(one_sheet_dic_of_one_peripheral: dict) -> dict:
    """
    从已获取的info_of_peripherals
    
    参数:
    - one_sheet_dic_of_one_peripheral: 一个外设的map页的信息
    
    返回:
    - 一个字典,key是寄存器名称, value是寄存器的详细信息
    """    
    
    try:
        sheetname = one_sheet_dic_of_one_peripheral['sheetname']  
        wb = one_sheet_dic_of_one_peripheral['wb']  
        sheet = wb[sheetname]  
        merged_cells = sheet.merged_cells.ranges
        file_path = one_sheet_dic_of_one_peripheral['file']  
    except Exception as e:
        print(f"[Error]读取Sheet\"{sheetname}\"时发生错误: {e}")
        return None
    
    headers = [cell.value for cell in sheet[1]] 

    RegDic = {}

    # 遍历每一行数据（第一行是表头,从第二行开始）
    for row_index, row in enumerate(sheet.iter_rows(min_row=2, values_only=True), start=2):
        
        row_width = len(row)
        if row_width < 36 :
            print(f"[Error]register[{row[1]}] in \"{sheetname}\" row_width < 36, from file [{file_path}]")
            continue
            
        reg_name = row[1]  # RegName在第二列
        
        if reg_name not in RegDic:
            RegDic[reg_name] = {
                "name": reg_name,  
                "addressOffset": row[0],  # 第一列是地址
                "resetValue": row[34],  # 第34列是ResetValue
                "description": row[35],  # 第35列是description
                "fields": {}
            }

        left_cell_value = None
        # 遍历当前行的每个cell（从第3列到第33列）
        for col_index in range(2, 34): # 从2 到 34-1
            cell_value_fieldname = row[col_index]
            thehead = headers[col_index]
            
            if cell_value_fieldname is not None:  # 只处理非空值,是每个cell一个field或者是一个合并单元格的第一个
                left_cell_value = cell_value_fieldname # 这个记录的实际是合并单元格的第一个
                if cell_value_fieldname.lower() in field_reserve_list: #如果是reserved,则跳过
                    continue
                if cell_value_fieldname not in RegDic[reg_name]["fields"]:
                    RegDic[reg_name]["fields"][cell_value_fieldname] = {
                        #'name' : cell_value_fieldname,
                        "msb": -1, "lsb": -1, "bits": []}

                # 将对应的列表头添加到集合中
                RegDic[reg_name]["fields"][cell_value_fieldname]["bits"].append(thehead)
            else: 
                # 对于空值要判断它是不是在merged_cells里面,如果是说明它还是一个field,如果不是,说明表格里面出现了一个不正常的空值
                cell_address = openpyxl.utils.get_column_letter(col_index + 1) + str(row_index)  # 计算单元格地址
                
                # 检查单元格是否在任何合并单元格范围内
                is_in_merged = False
                for merged in merged_cells:
                    min_col, min_row, max_col, max_row = merged.bounds
                    if min_row <= row_index <= max_row and min_col <= (col_index + 1) <= max_col:
                        is_in_merged = True
                        break

                if is_in_merged:
                    if (left_cell_value is not None) and ( left_cell_value.lower() not in field_reserve_list):
                        RegDic[reg_name]["fields"][left_cell_value]["bits"].append(thehead)
                else:
                    print(f"[Error][Field is empty] at {sheetname} of {file_path} for cell {cell_address}")

    # 计算msb和lsb
    for reg_name, reg_data in RegDic.items():
        for field_name, field_data in reg_data["fields"].items():
            bits = field_data["bits"]
            if bits:
                msb = max(bits)
                lsb = min(bits)
                field_data["msb"] = msb
                field_data["lsb"] = lsb
            else:
                field_data["msb"] = -1
                field_data["lsb"] = -1
            
            # 删除bits列表
            del field_data["bits"]

    # 检查msb和lsb
    for reg_name, reg_data in RegDic.items():
        for field_name, field_data in reg_data["fields"].items():
            if field_data["msb"] == -1 or field_data["lsb"] == -1:
                print(f"[Error][{reg_name}:{field_name}][bits parameter err] at {sheetname} of {file_path}")

    #print(RegDic)
    
    return RegDic
def read_reg_map(one_sheet_dic_of_one_peripheral: dict) -> dict:
    """
    从已获取的info_of_peripherals
    
    参数:
    - one_sheet_dic_of_one_peripheral: 一个外设的map页的信息
    
    返回:
    - 一个字典,key是寄存器名称, value是寄存器的详细信息
    
    peripherals_registers_info[peripheral][registname]["fields"][filedname] = {
        msb
        lab
    }
    
    peripherals_info_peripheral_fields[filedname] = {
        parameters
    }
    
        
    """    
    
    try:
        sheetname = one_sheet_dic_of_one_peripheral['sheetname']  
        wb = one_sheet_dic_of_one_peripheral['wb']  
        sheet = wb[sheetname]  
        merged_cells = sheet.merged_cells.ranges
        file_path = one_sheet_dic_of_one_peripheral['file']  
    except Exception as e:
        print(f"[Error]读取Sheet\"{sheetname}\"时发生错误: {e}")
        return None
    
    headers = [cell.value for cell in sheet[1]] 
        
    # 检查实际表头是否与预期一致
    h0 = valid_header_MAP
    h1 = headers
    if set(h1) != set(h0):
        missing = set(h0) - set(h1)
        extra = set(h1) - set(h0)
        print(f"[Forbidden] 表头检查不一致: 缺少 {missing}, 额外有 {extra} 在文件 {file_path}")
        sys.exit(10)
    
    RegDic = {}

    # 遍历每一行数据（第一行是表头,从第二行开始）
    for row_index, row in enumerate(sheet.iter_rows(min_row=2, values_only=True), start=2):
        
        row_width = len(row)
        if row_width < 4 :
            print(f"[Error]register[{row[1]}] in \"{sheetname}\" row_width < 4, from file [{file_path}]")
            continue
            
        if row[1] == None or row[1] == "":
            #print(f"[Notice]RegAdd[{row[0]}] in \"{sheetname}\" has no RegName")
            continue
        
        #reg_name = row[1]  # RegName在第二列
        reg_name = str.strip(row[1])
        
        def get_row_unit(unit) :
            if type(unit) == str:
                "" if unit == None else str.strip(unit)
            return unit
        
        if reg_name not in RegDic:
            RegDic[reg_name] = {
                "name": reg_name,  
                "addressOffset": get_row_unit(row[0]),  # 第一列是地址
                "resetValue": get_row_unit(row[2]),  # 第2列是ResetValue
                "description": get_row_unit(row[3]),  # 第3列是description
                "dim": get_row_unit(row[4]),  # 第3列是dim
                "dimIncrement": get_row_unit(row[5]),  # 第3列是dimIncrement
                "dimIndex": get_row_unit(row[6]),  # 第3列是dimIndex
                "fields": {}
            }

    #print(RegDic)
    
    return RegDic
def read_reg_detail(one_sheet_dic_of_one_peripheral: dict) -> dict:
 
    """
    从固定格式的工作表中获取键值对的字典,字典的key以index_form_0_of_col_as_key指定
    固定格式：表头(第一行)是属性名称，从第二行往下都是是对应属性的值
    对于多个key行,dics都传入key的list
    对于不连续的但是属于相同的Key的行,Key所在的Cell必须都等于Key
    对于连续的属于Key的行,Key位置的Cell可以为Key的值,也可以是空白
    
    参数:
    - one_in_sheet_dic: 已经获取到的工作簿和工作表数据的字典。
    - index_of_field: 指定列为输出字典的Key,默认为0,就是第一列
    
    返回:
    - 一个多同类对象的属性和值的键值dic list的字典,字典的key是对象名称,value是对象的属性的字典组成的list
    数据结构
    {
        "reg0" : {
            "field0" : [],
            "field1" : [],
        },
        "reg1" : {
            "field0" : [],
            "field1" : [],
        }
    }
    """
    
    one_in_sheet_dic=one_sheet_dic_of_one_peripheral
    index_of_field = 1
    index_of_reg = 0
    valid_headers=valid_header_DETAIL
    
    try:
        wb = one_in_sheet_dic['wb']  
        sheetname = one_in_sheet_dic['sheetname']
        sheet = wb[sheetname]  
        file_path = one_in_sheet_dic['file']
    except Exception as e:
        print(f"读取Sheet\"{sheetname}\"时发生错误: {e}")
        return None  
    
    if sheetname == "DMA_DETAIL" :
        pass
    
    result = {}
    
    # 读取表头
    header = [cell.value for cell in sheet[1]]  #rowindex 从1开始，col index从0开始，总觉得怎么这么狗血
    
    # 检查实际表头是否与预期一致
    if valid_headers is not None and len(valid_headers) > 0:
        h0 = valid_headers
        h1 = header
        if set(h1) != set(h0):
            missing = set(h0) - set(h1)
            extra = set(h1) - set(h0)
            print(f"[Forbidden] 表头检查不一致: 缺少 {missing}, 额外有 {extra} 在文件 {file_path}")
            sys.exit(11)
    
    row_count = sheet.max_row  # 获取总行数
    
        
    lastKey = "NotInitialed" #w为了防止表格中为了存在多个相同Key的多行,多行属于同一个Key的时候，Key的cell可能是空的，每次要记录一下上次的key
    lastRegname = "NotInitialed"
    for index, row in enumerate(sheet.iter_rows(min_row=2, max_row=row_count, values_only=True), start=2):  # 从第二行开始读取数据
        
        is_not_continuation_of_lastkey = True #表示当前这行不是上一个Key延续的空白Key或者重复Key 
        
        
        field = StrStrip(row[index_of_field])
        regname = StrStrip(row[index_of_reg])      
                        
        #首行判断,key不能为空
        if index == 2 : 
            if field == "" :
                print(f"[Error] First Key is EMPYT in sheet[{sheetname}] off file[{one_in_sheet_dic['file']}]! Stopping progress.")
                return None
        
        if (regname is None) or regname == '':
            regname = lastRegname
        else :
            lastRegname = regname
            
            if lastRegname == "" :
                pass  
            
        if (field is None):
            field = lastKey
            is_not_continuation_of_lastkey = False #空白Key被认为是同一个Key的多个延续行
        elif (field == lastKey) :
            is_not_continuation_of_lastkey = False #重复Key被认为是同一个Key的多个延续行
        else :
            field = str.strip(field)
            lastKey = field # 其它情况要更新这个记录        
                    
        # 将当前行转换为字典，key 为表头，value 为对应的单元格值        
        # 如果 is_not_dealing_enum == False，要把 row 读出来然后 row[index_of_field] 赋值为 lastKey 再打包成 row_dict
        row_list = list(row) 
        
        if (row_list[index_of_field] is None) and (not is_not_continuation_of_lastkey) :
            row_list[index_of_field] = lastKey 
        
        row_dict = {header[i]: row_list[i] for i in range(len(row_list))}
        
        #检查Key是不是已经存在dic里面了,不存在就创建Key的list
        if  regname not in result :
            result[regname] = {}
            
        if field not in result[regname] :
            result[regname][field] = []
            
        if lastRegname == "CMD" :
            pass  
        
        result[regname][field].append(row_dict)
            
    return result

def read_peripherals_registers_info(peripherals_overview_infos: dict)  -> dict:
    
    peripherals_registers_info = {}

    for peripheral, peripheral_dic in peripherals_overview_infos.items():
        
        #print(f"peripheral={peripheral}")
        
        #为外设创建一个字典
        peripherals_registers_info[peripheral] = {}
        
        #遍历这个外设的分sheet
        for part, part_dic in peripheral_dic.items():
            if part == "MAP":
                peripherals_registers_info[peripheral] = read_reg_map(part_dic)
            elif part == "DETAIL":
                peripherals_info_peripheral_fields = read_reg_detail(part_dic)
            else :
                print(f"[Error] unknown sheet ({part}) in [{part_dic['file']}]")
                
        for registername, reg_dics in peripherals_info_peripheral_fields.items():
            if registername == None :
                continue
            registername = str(registername).strip()
            if registername not in peripherals_registers_info[peripheral]:
                print(f"[Error]{peripheral}[{registername}], but [{registername}] is not in peripheral MAP sheet, pass this field")
                continue
            #print(f"registername={registername}")
            # 遍历peripherals_info_peripheral_fields，把每一个field 的信息增加到 belones2的reg里面
            for field_name, field_dics in reg_dics.items():
                
                if field_name.lower() in field_reserve_list:
                    continue;                    
                                    
                #如果 filed_name 不在 peripherals_registers_info[peripheral][registname]["fields"] 里面,则添加进去
                field_dic = field_dics[0]    
                fields_info = peripherals_registers_info[peripheral][registername]["fields"]
                if field_name not in fields_info:  
                    
                    msb = field_dic["msb"]
                    lsb = field_dic["lsb"]
                    def strisvalid(str):
                        return False if str == "" or str is None else True
                    
                    msb_valid = strisvalid(msb)
                    msb_not_valid = not msb_valid
                    lsb_valid = strisvalid(lsb)
                    lsb_not_valid = not lsb_valid
                    
                    if msb_not_valid and lsb_not_valid:
                        print(f"[Error]{registername}[{field_name}] msb and lsb are both empty")
                        return None
                    
                    elif msb_not_valid and lsb_valid :
                        try:
                            lsb = int(field_dic["lsb"])
                        except Exception as e:
                            print(f"[Error]{registername}[{field_name}] lsb value error")
                            return None
                        msb = lsb
                    elif msb_valid and  lsb_not_valid:
                        try:
                            msb = int(field_dic["msb"])
                        except Exception as e:
                            print(f"[Error]{registername}[{field_name}] msb value error")
                            return None
                        lsb = msb
                    else :
                        try:
                            msb = int(field_dic["msb"])
                            lsb = int(field_dic["lsb"])
                        except Exception as e:
                            print(f"[Error]{registername}[{field_name}] msb or lsb values error")
                            return None  
                    
                    fields_info[field_name] = {
                        "msb": msb,
                        "lsb": lsb
                    }  
                    skip_paras = list(fields_info[field_name].keys())
                    skip_paras = skip_paras + field_enum_parameter_list
                    for key,value in field_dic.items():
                        if key not in skip_paras:
                            fields_info[field_name][key] =value
                

                
                if field_dic["enumValueName"] != None and field_dic["enumValueName"] != "":
                    if "enumdict" not in fields_info[field_name]:
                        fields_info[field_name]["enumdict"] = {
                            "name" : field_dics[0]["headerEnumName"],
                            "values" : [] # 这是一个list,然后这个list里面是一堆dict
                            }
                    for fieldline in field_dics:
                        enumValueDict = {}  #每个dict的枚举信息
                        enumValueDict['enumValueName'] = fieldline['enumValueName']
                        enumValueDict['enumDescription'] = fieldline['enumDescription']
                        enumValueDict['enumValue'] = fieldline['enumValue']
                        fields_info[field_name]["enumdict"]["values"].append(enumValueDict)    
                        

                                

    return peripherals_registers_info
        

def get_peripherals_info(peripherals_overview_infos:dict ,peripherals_registers_info:dict,peripheral_alias : dict) -> dict:
    
    peripherals_info = copy.deepcopy(peripherals_overview_infos)

    
    #遍历寄存器记录,把里面的内容都拷贝到peripherals_info里面
    for peripheral_alia in peripherals_registers_info:
        if not peripheral_alia in peripheral_alias:
            #这是一个严重error,不允许继续
            raise Exception(f"[Error]peripheral[{peripheral_alia}] missed in sheetName in sheet \"PERIPHERALS\"")
        
        peripheral = peripheral_alias[peripheral_alia]
        if not peripheral in peripherals_info:
            print(f"[Error]peripheral[{peripheral}] missed in sheet \"PERIPHERALS\"")
            continue
        peripherals_info[peripheral]["registers"] = copy.deepcopy(peripherals_registers_info[peripheral_alia])   
        peripherals_info[peripheral]["has_registers"] = True
    
    return peripherals_info

